﻿using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using EssentialWebFramework.Models.Framework;
using Microsoft.Extensions.Configuration;

namespace EssentialWebFramework.Common
{
    /// <summary>
    /// Jwt 认证帮助类
    /// </summary>
    public class JwtHelper
    {
        /// <summary>
        /// 配置
        /// </summary>
        private IConfiguration _configuration { get; }

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="configuration"></param>
        public JwtHelper(IConfiguration configuration)
        {
            this._configuration = configuration;
        }

        /// <summary>
        /// 创建 Token
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="roleCodes"></param>
        /// <param name="isRememberMe"></param>
        /// <param name="tokenExpireTime"></param>
        /// <param name="refreshTokenExpireTime"></param>
        /// <returns></returns>
        public string CreateToken(string userId, List<string> roleCodes, 
            out DateTime tokenExpireTime, out DateTime refreshTokenExpireTime, bool isRememberMe = false)
        {
            IConfigurationSection jwtSection = _configuration.GetSection("JWT");

            // 1. 添加 Claim
            List<Claim> claims = new List<Claim>();
            // 1.1 添加用户id
            claims.Add(new Claim(ClaimTypes.Name, userId));
            // 1.2 添加用户角色
            claims.AddRange(roleCodes.Select(roleCode => new Claim(ClaimTypes.Role, roleCode)));

            int tokenExpireMinutes = jwtSection.GetValue<int>("ExpiresMinutes");

            // 如果勾选了记住我，则有效期翻倍
            if (isRememberMe)
            {
                tokenExpireMinutes = tokenExpireMinutes * 2;
            }

            tokenExpireTime = DateTime.Now.AddMinutes(tokenExpireMinutes);

            SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSection.GetValue<string>("SecurityKey")));
            SigningCredentials credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            JwtSecurityToken token = new JwtSecurityToken(
                                            issuer: jwtSection.GetValue<string>("Issuer"),
                                            audience: jwtSection.GetValue<string>("Audience"),
                                            claims: claims,
                                            expires: tokenExpireTime,
                                            signingCredentials: credentials);

            refreshTokenExpireTime = DateTime.Now.AddMinutes(jwtSection.GetValue<int>("RefreshTokenExpiresMinutes"));

            return new JwtSecurityTokenHandler().WriteToken(token);
        }


        /// <summary>
        /// JWT 验证参数
        /// </summary>
        public static readonly TokenValidationParameters ValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ClockSkew = TimeSpan.FromSeconds(30),

            ValidIssuer = GlobalConfig.Setting.JWT.Issuer,
            ValidAudience = GlobalConfig.Setting.JWT.Audience,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(GlobalConfig.Setting.JWT.SecurityKey))
        };

    }
}
